package com.hsh.annotations.aspect;

import com.alibaba.fastjson.JSON;
import com.hsh.annotations.annotation.OperationLog;
import com.hsh.service.IOperationLogService;
import com.hsh.tools.AddressUtil;
import com.hsh.tools.IPUtil;
import com.hsh.vo.dto.ActiveUser;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;

/**
 * 系统日志切面
 */
@Aspect
@Component
public class OperationLogAspect extends AspectSupport {
    private final Logger LOGGER = LoggerFactory.getLogger(this.getClass().getSimpleName());

    @Autowired
    IOperationLogService logService;

    @Pointcut("@annotation(com.hsh.annotations.annotation.OperationLog)")
    public void pointcut() {
    }

    //    @Pointcut("target(com.hsh.controller.TestController)")
//    @Pointcut("target(com.hsh.controller.TestController)")
    public void testCut() {
    }

    /**
     * 测试环绕通知
     *
     * @param point
     */
    @Around(value = "execution(* com.hsh.controller..*.*(..))")
//    @Around(value = "testCut()")
    public Object testCut(ProceedingJoinPoint point) throws Throwable {
        System.out.println("EXECUTION welcome");
        System.out.println("EXECUTION 调用方法:" + point.getSignature().getName());
        System.out.println("EXECUTION 目标对象：" + point.getTarget());
        System.out.println("EXECUTION 参数：" + point.getArgs());
//        System.out.println("EXECUTION 首个参数：" + point.getArgs()[0]);
        System.out.println();
        System.out.println();
        Object proceed = point.proceed();
        System.out.println("所调方法返回值: " + proceed);
        System.out.println();
        System.out.println();
        System.out.println("EXECUTION success");
        return proceed;
    }

    /**
     * 环绕通知
     *
     * @param joinPoint
     */
    @Around("pointcut()")
    public Object saveSysLog(ProceedingJoinPoint joinPoint) throws Throwable {
        com.hsh.entity.OperationLog sysLog = new com.hsh.entity.OperationLog();

        Object result = null;
        //开始时间
        long startTime = System.currentTimeMillis();

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        //获取注解varchar
        OperationLog controllerEndpoint = method.getAnnotation(OperationLog.class);
        if (controllerEndpoint != null) {
            String operation = controllerEndpoint.operation();
            //注解上的操作描述
            sysLog.setOperation(operation);
        }

        //请求的参数
        Object[] args = joinPoint.getArgs();
        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
        String[] paramNames = u.getParameterNames(method);
        sysLog.setParams("paramName:" + Arrays.toString(paramNames) + ",args:" + Arrays.toString(args));

        //操作人的真实姓名
        ActiveUser activeUser= (ActiveUser) SecurityUtils.getSubject().getPrincipal();
        // TODO 需要及时放开
//        sysLog.setNickname(activeUser.getUser().getNickname());
//        //操作人
//        sysLog.setUsername(activeUser.getUser().getUsername());

        sysLog.setNickname("admin");
        //操作人
        sysLog.setUsername("admin");

        String ipAddr = IPUtil.getIp();
        sysLog.setIp(ipAddr);
//        //地理位置
        sysLog.setLocation(AddressUtil.getCityInfo(ipAddr));
        //添加时间
        sysLog.setCreateTime(new Date());
        //执行目标方法
        result = joinPoint.proceed();
        //请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        sysLog.setMethod(className + "." + methodName + "()\n" + "\nresponse:" + postHandle(result));
        //执行耗时
        sysLog.setTime(System.currentTimeMillis() - startTime);
        //保存系统日志
        LOGGER.info("进入了日志~~~~~~~~~~~~~~~~");
        LOGGER.info("{}", sysLog);

        logService.saveLog(sysLog);
        return result;
    }

    /**
     * 返回数据
     */
    private String postHandle(Object retVal) {
        return Objects.nonNull(retVal) ? JSON.toJSONString(retVal) : "";
    }
}



